home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 3 / ct-rom iiib.zip / ct-rom iiib / OS2 / SPEL / PMGNUCHS / PMCHSSRC.ZIP / search.c < prev    next >
Text File  |  1994-04-21  |  38KB  |  1,469 lines

  1. /*
  2.  * search.c - C source for GNU CHESS
  3.  *
  4.  * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software
  5.  * Foundation
  6.  *
  7.  *  Project:    OS/2 PM Port of GNU CHESS 4.0 (PmChess)
  8.  *
  9.  *  Version:    1994-4-17
  10.  *
  11.  *   Module:    Search Module (search.c)
  12.  *
  13.  *   Porter:    Gnu Chess 4.0 Ported to OS/2 2.1+ by Yibing Fan
  14.  *
  15.  *   System:    OS/2 2.11 using emx0.8h
  16.  *
  17. //  Remarks:    This code is modified to work with PMchess
  18. //
  19.  * This file is part of GNU CHESS.
  20.  *
  21.  * GNU Chess is free software; you can redistribute it and/or modify it under
  22.  * the terms of the GNU General Public License as published by the Free
  23.  * Software Foundation; either version 2, or (at your option) any later
  24.  * version.
  25.  *
  26.  * GNU Chess is distributed in the hope that it will be useful, but WITHOUT ANY
  27.  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  28.  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  29.  * details.
  30.  *
  31.  * You should have received a copy of the GNU General Public License along with
  32.  * GNU Chess; see the file COPYING.  If not, write to the Free Software
  33.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  34.  */
  35.  
  36. #define INCL_DOS
  37. #define INCL_DOSPROCESS
  38. #define INCL_PM
  39. #include <os2.h>
  40. #include <string.h>
  41. #include <time.h>
  42. #include <stdlib.h>
  43. #include <stdio.h>
  44. #include "PmChess.h"
  45. #include "GnuChess.h"
  46. #include "Defs.h"
  47.  
  48. short background = 0;
  49. static short int DepthBeyond;
  50. unsigned short int PrVar[MAXDEPTH];
  51. extern char mvstr[4][6];
  52. extern short int recycle, ISZERO;
  53. #ifdef NULLMOVE
  54. short int null;            /* Null-move already made or not */
  55. short int PVari;        /* Is this the PV */
  56. #endif
  57. short int zwndw;
  58. unsigned int TTadd = 1;
  59. short int recycle;
  60.  
  61. #if ttblsz
  62.  
  63. #define CB(i) (unsigned char) ((color[2 * (i)] ? 0x80 : 0)\
  64.            | (board[2 * (i)] << 4)\
  65.            | (color[2 * (i) + 1] ? 0x8 : 0)\
  66.            | (board[2 * (i) + 1]))
  67. inline
  68. int
  69. ProbeTTable (short int side,
  70.          short int depth,
  71.          short int ply,
  72.          short int *alpha,
  73.          short int *beta,
  74.          short int *score)
  75.  
  76. /*
  77.  * Look for the current board position in the transposition table.
  78.  */
  79.  
  80. {
  81.   register struct hashentry *ptbl;
  82.   register /*unsigned*/ short i = 0;    /*to match new type of rehash --tpm*/
  83.  
  84.   ptbl = &ttable[side][hashkey % ttblsize];
  85.   while (true)
  86.     {
  87.       if (ptbl->depth == 0)
  88.     return false;
  89.       if (ptbl->hashbd == hashbd)
  90.     break;
  91.       if (++i > rehash)
  92.     return false;
  93.       ptbl++;
  94.     }
  95.  
  96.   /* rehash max rehash times */
  97.   PV = SwagHt = ptbl->mv;
  98.   if ((ptbl->depth >= (short) depth))
  99.     {
  100.  
  101.  
  102. #ifndef BAREBONES
  103.       HashCnt++;
  104. #endif
  105.       if (ptbl->flags & truescore)
  106.     {
  107.       *score = ptbl->score;
  108.       /* adjust *score so moves to mate is from root */
  109.       *beta = -20000;
  110.     }
  111.       else if (ptbl->flags & lowerbound)
  112.     {
  113.       if (ptbl->score > *alpha)
  114.         *alpha = ptbl->score - 1;
  115.     }
  116.       return (true);
  117.     }
  118.   return (false);
  119. }
  120.  
  121. inline
  122. int
  123. PutInTTable
  124.  (short int side,
  125.          short int score,
  126.          short int depth,
  127.          short int ply,
  128.          short int alpha,
  129.          short int beta,
  130.          short unsigned int mv)
  131.  
  132. /*
  133.  * Store the current board position in the transposition table.
  134.  */
  135.  
  136. {
  137.   register struct hashentry *ptbl;
  138.   register /*unsigned*/ short i = 0;    /*to match new type of rehash --tpm*/
  139.  
  140.   ptbl = &ttable[side][hashkey % ttblsize];
  141.   while (true)
  142.     {
  143.       if (ptbl->depth == 0 || ptbl->hashbd == hashbd)
  144.     break;
  145.       if (++i > rehash)
  146.     {
  147. #ifndef BAREBONES
  148.       THashCol++;
  149. #endif
  150.       ptbl += recycle;
  151.       break;
  152.     }
  153.       ptbl++;
  154.     }
  155.  
  156. #ifndef BAREBONES
  157.   TTadd++;
  158.   HashAdd++;
  159. #endif
  160.   /* adjust score so moves to mate is from this ply */
  161.   ptbl->hashbd = hashbd;
  162.   ptbl->depth = (unsigned char) depth;
  163.   ptbl->score = score;
  164.   ptbl->mv = mv;
  165.   if (score > beta)
  166.     {
  167.       ptbl->flags = lowerbound;
  168.       ptbl->score = beta + 1;
  169.     }
  170.   else
  171.     ptbl->flags = truescore;
  172.  
  173.   return true;
  174. }
  175.  
  176. #endif
  177.  
  178. #include "ataks.h"
  179.  
  180. #include "debug41.h"
  181. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  182. inline
  183. short int
  184. repetition ()
  185.  
  186. /*  Check for draw by threefold repetition.  */
  187.  
  188. {
  189.   register short i, c, cnt;
  190.   register unsigned short m;
  191.   short b[64];
  192.  
  193.   cnt = c = 0;
  194.   /* try to avoid work */
  195.   if (GameCnt > Game50 + 4)
  196.     {
  197.       for (i = 0; i < 64; b[i++] = 0);
  198.       for (i = GameCnt; i >= Game50; i--)
  199.     {
  200.       m = GameList[i].gmove;
  201.       /* does piece exist on diff board? */
  202.       if (b[m & 0x3f])
  203.         {
  204.           /* does diffs cancel out, piece back? */
  205.           if ((b[m >> 8] += b[m & 0x3f]) == 0)
  206.         --c;
  207.           b[m & 0x3f] = 0;
  208.         }
  209.       else
  210.         {
  211.           /* create diff */
  212.           ++c;
  213.           /* does diff cancel out another diff? */
  214.           if (!(b[m >> 8] -= (b[m & 0x3f] = board[m & 0x3f] +
  215.                   (color[m & 0x3f] << 8))))
  216.         --c;;
  217.         }
  218.       /* if diff count is 0 we have a repetition */
  219.       if (c == 0)
  220.         if ((i ^ GameCnt) & 1)
  221.           cnt++;
  222.     }
  223.     }
  224.   return cnt;
  225. }
  226.  
  227. int plyscore, globalscore;
  228. int
  229. pick (short int p1, short int p2)
  230.  
  231. /*
  232.  * Find the best move in the tree between indexes p1 and p2. Swap the best
  233.  * move into the p1 element.
  234.  *
  235.  */
  236. {
  237.   register struct leaf *p, *q, *r, *k;
  238.   register s0;
  239.   struct leaf temp;
  240.  
  241.   k = p = &Tree[p1];
  242.   q = &Tree[p2];
  243.   s0 = p->score;
  244.   for (r = p + 1; r <= q; r++)
  245.     if ((r->score) > s0)
  246.       {
  247.     s0 = (r->score);
  248.     p = r;
  249.       }
  250.   if (p != k)
  251.     {
  252.       temp = *p;
  253.       *p = *k;
  254.       *k = temp;
  255.       return true;
  256.     }
  257.   return false;
  258. }
  259.  
  260. int bookflag = false;
  261. int Jscore = 0;
  262.  
  263. static int TCcount, TCleft;
  264. void
  265. SelectMove ( short int side, short int iop)
  266.  
  267.  
  268. /*
  269.  * Select a move by calling function search() at progressively deeper ply
  270.  * until time is up or a mate or draw is reached. An alpha-beta window of
  271.  * -Awindow to +Bwindow points is set around the score returned from the
  272.  * previous iteration. If Sdepth != 0 then the program has correctly
  273.  * predicted the opponents move and the search will start at a depth of
  274.  * Sdepth+1 rather than a depth of 1.
  275.  */
  276.  
  277. {
  278.   static short int i, tempb, tempc, tempsf, tempst, xside, rpt;
  279.   static short int alpha, beta, score;
  280.   static struct GameRec *g;
  281.   extern HWND hwndClient;
  282. /*  unsigned long j;*/
  283.  
  284.   flag.timeout = false;
  285.   flag.back = false;
  286.   flag.musttimeout = false;
  287.   xside = side ^ 1;
  288.   recycle = (GameCnt % rehash) - rehash;
  289.   /* if background mode set to infinite */
  290.   if (iop == 2)
  291.     {
  292.       ResponseTime = 9999999;
  293.       background = true;
  294.     }
  295.   else
  296.     {
  297.       player = side;
  298.       if (TCflag)
  299.     {
  300.       TCcount = 0;
  301.       background = false;
  302.       if (TimeControl.moves[side] < 1)
  303.         TimeControl.moves[side] = 1;
  304.       /* special case time per move specified */
  305.       if (flag.onemove)
  306.         {
  307.           ResponseTime = TimeControl.clock[side] - 100;
  308.           TCleft = 0;
  309.         }
  310.       else
  311.         {
  312.           /* calculate avg time per move remaining */
  313.           TimeControl.clock[side] += TCadd;
  314.  
  315.           ResponseTime = (TimeControl.clock[side]) / (((TimeControl.moves[side]) * 2) + 1);
  316.           TCleft = (int) ResponseTime / 3;
  317.           ResponseTime += TCadd / 2;
  318.           if (TimeControl.moves[side] < 5)
  319.         TCcount = MAXTCCOUNTX - 10;
  320.         }
  321.       if (ResponseTime < 101)
  322.         {
  323.           ResponseTime = 100;
  324.           TCcount = MAXTCCOUNTX - 10;
  325.         }
  326.       else if (ResponseTime < 200)
  327.         {
  328.           TCcount = MAXTCCOUNTX - 10;
  329.         }
  330.     }
  331.       else
  332.     {
  333.       ResponseTime = MaxResponseTime;
  334.       TCleft = 0;
  335.       ElapsedTime (1);
  336.     }
  337.       if (TCleft)
  338.     {
  339.       TCcount = ((int) ((TimeControl.clock[side] - ResponseTime)) / 2) / TCleft;
  340.       if (TCcount > MAXTCCOUNTX)
  341.         TCcount = 0;
  342.       else
  343.         TCcount = MAXTCCOUNTX - TCcount;
  344.     }
  345.       else
  346.     TCcount = MAXTCCOUNTX;
  347.     }
  348.  
  349.   if (Sdepth > 0)
  350.     {
  351.       time0 = time(NULL);
  352. //      time0 = ft;
  353.       goto SS;
  354.     } 
  355.   ExtraTime = 0;
  356.   ExaminePosition ();
  357.   score = ScorePosition (side);
  358. //#ifdef QUIETBACKGROUND
  359. //  if (!background)
  360. //#endif /* QUIETBACKGROUND */
  361. //    ShowSidetoMove ();
  362. #ifdef QUIETBACKGROUND
  363.   if (!background)
  364. #endif /* QUIETBACKGROUND */
  365.     SearchStartStuff (side);
  366. #ifdef HISTORY
  367. #if (defined(NOMEMSET) || defined(MSDOS)) && !defined(__GNUC__)
  368.   for (j = 0; j <= 32768; j++)
  369.     history[j] = 0;
  370. #else
  371.   memset ((unsigned char *) history, 0, (unsigned long) sizeof (history));
  372. #endif /* NOMEMSET */
  373. #endif
  374.   FROMsquare = TOsquare = -1;
  375.   PV = 0;
  376.   if (iop == 1)
  377.     hint = 0;
  378.   for (i = 0; i < MAXDEPTH; i++)
  379.     PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  380.   /* set initial window for search */
  381.   alpha = score - ((computer == black) ? BAwindow : WAwindow);
  382.   beta = score + ((computer == black) ? BBwindow : WBwindow);
  383.   rpt = 0;
  384.   TrPnt[1] = 0;
  385.   root = &Tree[0];
  386.   MoveList (side, 1);
  387.   for (i = TrPnt[1]; i < TrPnt[2]; i++)
  388.     if (!pick (i, TrPnt[2] - 1))
  389.       break;
  390.   /* can I get a book move? */
  391.   if (flag.regularstart && Book)
  392.     {
  393.       flag.timeout = bookflag = OpeningBook (&hint, side);
  394.       if (TCflag)
  395.     ResponseTime += ResponseTime;
  396.     }
  397.   /* zero stats for hash table */
  398.   reminus = replus = 0;
  399.   GenCnt = NodeCnt = ETnodes = EvalNodes = HashCnt = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0;
  400.   globalscore = plyscore = score;
  401.   Jscore = 0;
  402.   zwndw = 20;
  403. #include "debug4.h"
  404.   /********************* main loop ********************************/
  405.   Sdepth = (MaxSearchDepth < (MINDEPTH - 1)) ? MaxSearchDepth : (MINDEPTH - 1);
  406.   while (!flag.timeout)
  407.     {
  408.       /* go down a level at a time */
  409.       Sdepth++;
  410. #ifdef NULLMOVE
  411.       null = 0;
  412.       PVari = 1;
  413. #endif
  414.       DepthBeyond = Sdepth + ((Sdepth == 1) ? 7 : 11);
  415.  
  416. #ifndef BAREBONES
  417. #ifdef QUIETBACKGROUND
  418.       if (!background)
  419. #endif /* QUIETBACKGROUND */
  420.     ShowDepth (' ');
  421. #endif
  422.       /* search at this level returns score of PV */
  423.       score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  424.       /* save PV as killer */
  425.       for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i];
  426.  
  427.       /* low search failure re-search with (-inf,score) limits  */
  428.       if (score < alpha)
  429.     {
  430. #ifndef BAREBONES
  431.       reminus++;
  432. #ifdef QUIETBACKGROUND
  433.       if (!background)
  434. #endif /* QUIETBACKGROUND */
  435.         ShowDepth ('-');
  436. #endif
  437.       if (TCflag && TCcount < MAXTCCOUNTR)
  438.         {
  439.           TCcount = MAXTCCOUNTR - 1;
  440.           ExtraTime += (8 * TCleft);
  441.         }
  442.  
  443.       score = search (side, 1, Sdepth, -9999, 9999, PrVar, &rpt);
  444.     }
  445.       /* high search failure re-search with (score, +inf) limits */
  446.       else if (score > beta && !(root->flags & exact))
  447.     {
  448. #ifndef BAREBONES
  449.       replus++;
  450. #ifdef QUIETBACKGROUND
  451.       if (!background)
  452. #endif /* QUIETBACKGROUND */
  453.         ShowDepth ('+');
  454. #endif
  455.       score = search (side, 1, Sdepth, -9999, 9999, PrVar, &rpt);
  456.     }
  457.       /****************jump to here from Sdepth >0 condition ***************/
  458. SS:
  459.       if (flag.musttimeout || Sdepth >= MaxSearchDepth)
  460.     flag.timeout = true;
  461.  
  462.       else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNTR))
  463.     {
  464.       if (killr0[1] != PrVar[1] /* || Killr0[2] != PrVar[2] */ )
  465.         {
  466.           TCcount++;
  467.           ExtraTime += TCleft;
  468.         }
  469.       if ((abs (score - globalscore) / Sdepth) > ZDELTA)
  470.         {
  471.           TCcount++;
  472.           ExtraTime += TCleft;
  473.         }
  474.     }
  475.       if (score > (Jscore - zwndw) && score > (Tree[1].score + 250))
  476.     ExtraTime = 0;
  477.       ElapsedTime (2); 
  478.       if (root->flags & exact)
  479.     flag.timeout = true;
  480.       /*else if (Tree[1].score < -9000) flag.timeout = true;*/
  481. #if defined OLDTIME || !defined HASGETTIMEOFDAY
  482.       else if (!(Sdepth < MINDEPTH) && TCflag && ((4 * et) > (2 * ResponseTime + ExtraTime)))
  483.     flag.timeout = true;
  484. #else
  485.       else if (!(Sdepth < MINDEPTH) && TCflag &&
  486.            ((int) (1.93913099l * (pow ((double) et, 1.12446928l))) > (ResponseTime + ExtraTime)))
  487.     flag.timeout = true;
  488. #endif
  489.       /************************ time control ***********************************/
  490.  
  491.       /* save PV as killer */
  492.       for (i = 1; i <= Sdepth + 1; i++)
  493.     killr0[i] = PrVar[i];
  494.       if (!flag.timeout)
  495.     Tscore[0] = score;
  496.       /* if (!flag.timeout) */
  497. /*
  498.       for (i = TrPnt[1] + 1; i < TrPnt[2]; i++)
  499.     if (!pick (i, TrPnt[2] - 1))
  500.       break;
  501. */
  502.       /* if done or nothing good to look at quit */
  503.       if ((root->flags & exact) || (score < -9000))
  504.     flag.timeout = true;
  505.       /* find the next best move put below root */
  506. #include "debug13.h"
  507.       if (!flag.timeout)
  508.     {
  509.       /* */
  510. #if !defined NODYNALPHA
  511.       Jscore = (plyscore + score) >> 1;
  512. #endif
  513.       zwndw = 20 + abs (Jscore / 12);
  514.       plyscore = score;
  515.       /* recompute search window */
  516.       beta = score + ((computer == black) ? BBwindow : WBwindow);
  517. #if !defined NODYNALPHA
  518.       alpha = ((Jscore < score) ? Jscore : score) - ((computer == black) ? BAwindow : WAwindow) - zwndw;
  519. #else
  520.       alpha = score - ((computer == black) ? BAwindow : WAwindow);
  521. #endif
  522.     }
  523. #ifndef BAREBONES
  524. #ifdef QUIETBACKGROUND
  525.       if (!background)
  526. #endif /* QUIETBACKGROUND */
  527.     ShowResults (score, PrVar, '.');
  528. #ifdef DEBUG41
  529.       debug41 (score, PrVar, '.');
  530. #endif
  531. #endif
  532. #include "debug16.h"
  533.     }
  534.   /******************************* end of main loop ***********************************/
  535.   /* background mode */
  536.   if (iop == 2)
  537.     return;
  538. #include "debug4.h"
  539.   if (rpt >= 2)
  540.     {
  541.       root->flags |= draw;
  542.       DRAW = CP[101];        /* Repetition */
  543.     }
  544.   else
  545.     /* if no moves and not in check then draw */
  546.   if ((score == -9999) && !(SqAtakd (PieceList[side][0], xside)))
  547.     {
  548.       root->flags |= draw;
  549.       DRAW = CP[87];        /* No moves */
  550.     }
  551.   else if (GameCnt == MAXMOVES)
  552.     {
  553.       root->flags |= draw;
  554.       DRAW = CP[80];        /* Max Moves */
  555.     }
  556.   /* not in book so set hint to guessed move for other side */
  557.   if (!bookflag)
  558.     hint = ((PrVar[1]) ? PrVar[2] : 0);
  559.  
  560.   /* if not mate or draw make move and output it */
  561.   if (((score > -9999) && (rpt <= 2)) || (root->flags & draw))
  562.     {
  563.       MakeMove (side, &Tree[0], &tempb, &tempc, &tempsf, &tempst, &INCscore);
  564. #if !defined NOMATERIAL
  565.       if (flag.material && !pmtl[black] && !pmtl[white] && (mtl[white] < (valueR + valueK)) && (mtl[black] < (valueR + valueK)))
  566.     {
  567.       root->flags |= draw;
  568.       DRAW = CP[224];    /* No pieces */
  569.     }
  570.       else
  571. #endif
  572.       if (!PieceCnt[black] && !PieceCnt[white])
  573.     {
  574.       root->flags |= draw;
  575.       DRAW = CP[88];    /* No pieces */
  576.     }
  577.       algbr (root->f, root->t, (short) root->flags);
  578.     }
  579.   else
  580.     {
  581.       algbr (0, 0, 0);        /* Zero move string when mate. */
  582.       root->score = score;    /* When mate, ignore distinctions!
  583.                  * --SMC */
  584.     }
  585.   g = &GameList[GameCnt];
  586.   if (g->flags & capture && g->piece == king)
  587.     {
  588.       flag.mate = flag.illegal = true;
  589.     }
  590.   /* If Time Control get the elapsed time */
  591.   if (TCflag)
  592.     ElapsedTime (1);
  593.   OutputMove (hwndClient);
  594.   /* if mate set flag */
  595.   if ((score == -9999 || score == 9998))
  596.     flag.mate = true;
  597.   /* if mate clear hint */
  598.   if (flag.mate)
  599.     hint = 0;
  600.   /* if pawn move or capture or castle or promote zero repitition array */
  601.   if ((board[root->t] == pawn) || (root->flags & (capture | cstlmask | promote)))
  602.     {
  603.       Game50 = GameCnt;
  604.       ZeroRPT ();
  605.     }
  606.   /* add move to game list */
  607.   g->score = score;
  608.   g->nodes = NodeCnt;
  609.   g->time = (et + 50) / 100;
  610.   g->depth = Sdepth;
  611. #include "debug40.h"
  612.   /* update time comtrol info */
  613.   if (TCflag)
  614.     {
  615.       TimeControl.clock[side] -= (et + OperatorTime);
  616. //      timecomp[compptr] = (et + OperatorTime);
  617.       /* finished our required moves - setup the next set */
  618.       --TimeControl.moves[side];
  619.     }
  620.   /* check for end conditions */
  621.   if ((root->flags & draw) /* && flag.bothsides */ )
  622.     flag.mate = true;
  623.   else if (GameCnt == MAXMOVES)
  624.     {
  625.       flag.mate = true;
  626.     }
  627.   /* out of move store, you loose */
  628.   else
  629.     /* switch to other side */
  630.     player = xside;
  631.   Sdepth = 0;
  632. }
  633.  
  634.  
  635. int
  636. search (short int side,
  637.     register short int ply,
  638.     register short int depth,
  639.     short int alpha,
  640.     short int beta,
  641.     short unsigned int *bstline,
  642.     short int *rpt)
  643.  
  644. /*
  645.  * Perform an alpha-beta search to determine the score for the current board
  646.  * position. If depth <= 0 only capturing moves, pawn promotions and
  647.  * responses to check are generated and searched, otherwise all moves are
  648.  * processed. The search depth is modified for check evasions, certain
  649.  * re-captures and threats. Extensions may continue for up to 11 ply beyond
  650.  * the nominal search depth.
  651.  */
  652.  
  653. {
  654.   register short j, pnt;
  655.   short tempb, tempc, tempsf, tempst, rc;
  656.   short xside, pbst, score, rcnt, slk, InChk;
  657.   unsigned short mv, nxtline[MAXDEPTH];
  658.   struct leaf *node, tmp;
  659.   short best = -12000;
  660.   extern short Best;       /* Globel, the same as best, update only  */
  661. //  extern short pntext;       /* Globel, for update current move only  */
  662.   extern USHORT *Bstline;
  663.   extern CHAR Bch;
  664.   short bestwidth = 0;      /* when needed for other thread */
  665. #ifdef NULLMOVE
  666.   short int PVsave;
  667.   short int PVarisave;
  668. #endif
  669.   NodeCnt++;
  670.   /* look every ZNODE nodes for a timeout */
  671. #ifdef NULLMOVE
  672.   if (!null)
  673.     {
  674. #endif
  675.       if (NodeCnt > ETnodes)
  676.     {
  677.       ElapsedTime (2);
  678.       if (flag.back)
  679.         {
  680.           flag.back = false;
  681.           flag.timeout = true;
  682.           flag.musttimeout = false;
  683.         }
  684.       else if (TCflag || MaxResponseTime)
  685.         {
  686.           if ((et >= (ResponseTime + ExtraTime)) && Sdepth > MINDEPTH )
  687.         {        /* try to extend to finish ply */
  688.           if (flag.back || (TCflag && TCcount < MAXTCCOUNTX))
  689.             {
  690.               flag.back = false;
  691.               flag.musttimeout = true;
  692.               TCcount += 1;
  693.               ExtraTime += TCleft;
  694.             }
  695.           else
  696.             {
  697.               flag.back = false;
  698.               flag.timeout = true;
  699.               flag.musttimeout = false;
  700.             }
  701.         }
  702.         }
  703.       else if (flag.back)
  704.         {
  705.           flag.back = false;
  706.           flag.timeout = true;
  707.           flag.musttimeout = false;
  708.         }
  709.  
  710.     }
  711.       else if (!TCflag && flag.musttimeout && Sdepth > MINDEPTH)
  712.     {
  713.       flag.timeout = true;
  714.       flag.musttimeout = false;
  715.     }
  716. #ifdef NULLMOVE
  717.     }
  718. #endif
  719.   xside = side ^ 1;
  720.   /* slk is lone king indicator for either side */
  721.   score = evaluate (side, ply, alpha, beta, INCscore, &InChk);
  722.  
  723.   /*
  724.    * check for possible repitition if so call repitition - rpt is
  725.    * repeat count
  726.    */
  727.   if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
  728.     {
  729.       *rpt = repetition ();
  730.  
  731.       /*
  732.        * repeat position >2 don't need to return score it's taken
  733.        * care of above
  734.        */
  735.       if (*rpt == 1)
  736.     score /= 2;
  737.     }
  738.   else
  739.     *rpt = 0;
  740.  
  741.   /* score > 9000 its a draw or mate */
  742.   if (score > 9000)
  743.     {
  744.       bstline[ply] = 0;
  745.       return (score);
  746.     }
  747.   /* Do we need to add depth because of special conditions */
  748.   /* if in check or pawn threat or in capture sequence search deeper */
  749.   /*************************************** depth extensions ***********************************/
  750.   if (depth > 0)
  751.     {
  752.       /* Allow opponent a chance to check again */
  753.       if (InChk)
  754.     depth = (depth < 2) ? 2 : depth;
  755.       else if (PawnThreat[ply - 1] ||
  756.            (flag.rcptr && (score > alpha) &&
  757.       (score < beta) && (ply > 2) && CptrFlag[ply - 1] && CptrFlag[ply - 2]))
  758.     ++depth;
  759.     }
  760.   else
  761.     {
  762.       if (score >= alpha &&
  763.       (InChk || PawnThreat[ply - 1] || (hung[side] > 1 && ply == Sdepth + 1)))
  764.     depth = 1;
  765.       else if (score <= beta &&
  766.            ((ply < Sdepth + 4) && (ply > 4) &&
  767.         ChkFlag[ply - 2] && ChkFlag[ply - 4] &&
  768.         ChkFlag[ply - 2] != ChkFlag[ply - 4]))
  769.     depth = 1;
  770.     }
  771.   /*******************************************************************************************/
  772.   /* try the local transition table if it's there */
  773. #if ttblsz
  774.   if ( /*depth > 0 &&*/ flag.hash && ply > 1)
  775.     {
  776.       if (ProbeTTable (side, depth, ply, &alpha, &beta, &score) == true)
  777.     {
  778.       bstline[ply] = PV;
  779.       bstline[ply + 1] = 0;
  780. #include "debug64.h"
  781.       if (beta == -20000)
  782.         return (score);
  783.       if (alpha > beta)
  784.         return (alpha);
  785.     }
  786. #ifdef HASHFILE
  787.       /* ok try the transition file if its there */
  788.       else if (hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit)
  789.      && (ProbeFTable (side, depth, ply, &alpha, &beta, &score) == true))
  790.     {
  791.           PutInTTable (side, score, depth, ply, alpha, beta, PV);
  792.           bstline[ply] = PV;
  793.           bstline[ply + 1] = 0;
  794.           if (beta == -20000)
  795.         return (score);
  796.           if (alpha > beta)
  797.         return (alpha);
  798. #include "debug10.h"
  799.     }
  800. #endif /* HASHFILE */
  801.     }
  802. #endif /* ttblsz */
  803.  
  804.   /*
  805.    * if more then DepthBeyond ply past goal depth or at goal depth and
  806.    * score > beta quit - means we are out of the window
  807.    */
  808.   if (ply > DepthBeyond || (depth < 1 && score > beta))
  809.     {
  810.       return (score);
  811.     }
  812.  
  813.   /*
  814.    * if below first ply and not at goal depth generate all moves else
  815.    * only capture moves
  816.    */
  817.   if (ply > 1)
  818.     if (depth > 0 || ply < (SDEPTHLIM) ||
  819.     (background && ply < Sdepth + 2))
  820.       {
  821.     MoveList (side, ply);
  822.       }
  823.     else
  824.       {
  825.     CaptureList (side, ply);
  826.       }
  827.  
  828.   /* no moves return what we have */
  829.  
  830.   /*
  831.    * normally a search will continue til past goal and no more capture
  832.    * moves exist
  833.    */
  834.   /* unless it hits DepthBeyond */
  835.   if (TrPnt[ply] == TrPnt[ply + 1])
  836.     {
  837.       return (score);
  838.     }
  839.  
  840.  
  841.  
  842.   /* if not at goal set best = -inf else current score */
  843.   best = (depth > 0) ? -12000 : score;
  844. #ifdef NULLMOVE
  845.  
  846.   PVarisave = PVari;
  847.   if (!null &&            /* no previous null-move */
  848.       !PVari &&            /* no null-move during the PV */
  849.       (ply > 2) &&        /* not at ply 1 */
  850.       (ply <= Sdepth) &&
  851.       (depth > 3) &&
  852.       !InChk &&            /* no check */
  853.       ((mtl[side] + mtl[xside]) > NULLMOVELIM))
  854.     /* enough material such that zugzwang is unlike but who knows which value
  855.        is suitable? */
  856.     {
  857.  
  858.       /* ok, we make a null move, i.e.  this means we have nothing to do
  859.       but we have to keep the some arrays up to date otherwise gnuchess
  860.       gets confused.  Maybe somebody knows exactly which informations are
  861.      important and which not.
  862.  
  863.      Another idea is that we try the null-move first and generate the
  864.      moves later.  This may save time but we have to take care that
  865.      PV and other variables contain the right value so that the move
  866.      ordering works right.
  867.      */
  868.       register struct GameRec *g;
  869.  
  870.       nxtline[ply + 1] = 0;
  871.       CptrFlag[ply] = 0;
  872.       PawnThreat[ply] = 0;
  873.       Tscore[ply] = score;
  874.       PVsave = PV;
  875.       PV = 0;
  876.       null = 1;
  877.       g = &GameList[++GameCnt];
  878.       g->hashkey = hashkey;
  879.       g->hashbd = hashbd;
  880.       epsquare = -1;
  881.       TOsquare = -1;
  882.       g->Game50 = Game50;
  883.       g->gmove = -1;
  884.       g->flags = 0;
  885.       g->piece = 0;
  886.       g->color = neutral;
  887.  
  888.       best = -search (xside, ply + 1, depth - 2, -beta - 1, -beta, nxtline, &rcnt);
  889.       null = 0;
  890.       PV = PVsave;
  891.       GameCnt--;
  892.     if (best < alpha) best = -12000;
  893.       else if (best > beta) return (best);
  894.       else best = -12000;
  895.     }
  896. #endif
  897.   /* if best so far is better than alpha set alpha to best */
  898.   if (best > alpha)
  899.     alpha = best;
  900.   /********************** main loop ************************************************************************/
  901.   /* look at each move until no more or beta cutoff */
  902.   for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] && best <= beta; pnt++)
  903.     {
  904.       /* find the most interesting looking of the remaining moves */
  905.       if (ply > 1)
  906.     pick (pnt, TrPnt[ply + 1] - 1);
  907. #ifdef NULLMOVE
  908.       PVari = PVarisave && (pnt == TrPnt[ply]);    /* Is this the PV? */
  909. #endif
  910.  
  911.       node = &Tree[pnt];
  912.       /* is this a forbidden move */
  913.       if (ply == 1 && node->score == -32768) continue;
  914.       nxtline[ply + 1] = 0;
  915.  
  916. #ifndef BAREBONES
  917.       /* if at top level */
  918.       if (ply == 1)
  919.     {            /* at the top update search status */
  920.       if (flag.post)
  921. #ifdef QUIETBACKGROUND
  922.         if (!background)
  923. #endif /* QUIETBACKGROUND */
  924.           ShowCurrentMove (pnt, node->f, node->t);
  925.     }
  926. #endif
  927.       if (!(node->flags & exact))
  928.     {
  929.       /* make the move and go deeper */
  930.       MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  931.       CptrFlag[ply] = (node->flags & capture);
  932.       PawnThreat[ply] = (node->flags & pwnthrt);
  933.       Tscore[ply] = node->score;
  934.       PV = node->reply;
  935.       node->score = -search (xside, ply + 1,
  936.                  (depth > 0) ? depth - 1 : 0,
  937.                  -beta, -alpha,
  938.                  nxtline, &rcnt);
  939. /*
  940.           if(!flag.timeout)node->score = score;
  941. */
  942.       node->width = (ply % 2 == 1) ? (TrPnt[ply + 2] - TrPnt[ply + 1]) : 0;
  943.       if (abs (node->score) > 9000)
  944.         node->flags |= exact;
  945.       else if (rcnt == 1)
  946.         node->score /= 2;
  947. #include "debug256.h"
  948.       if ((rcnt >= 2 || GameCnt - Game50 > 99 || (node->score == 9999 - ply && !ChkFlag[ply])))
  949.         {
  950.           node->flags |= (draw | exact);
  951.           DRAW = CP[58];    /* Draw */
  952.           node->score = ((side == computer) ? contempt : -contempt);
  953.         }
  954.       node->reply = nxtline[ply + 1];
  955.       /* reset to try next move */
  956.       UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  957.     }
  958.       /* if best move so far */
  959.       if (!flag.timeout && ((node->score > best) || ((node->score == best) && (node->width > bestwidth))))
  960.     {
  961.       /*
  962.        * all things being equal pick the denser part of the
  963.        * tree
  964.        */
  965.       bestwidth = node->width;
  966.  
  967.       /*
  968.        * if not at goal depth and better than alpha and not
  969.        * an exact score increment by depth
  970.        */
  971.       if (depth > 0 && node->score > alpha && !(node->flags & exact))
  972.         node->score += depth;
  973.       best = node->score;
  974.       pbst = pnt;
  975.       if (best > alpha)
  976.         {
  977.           alpha = best;
  978.         }
  979.       /* update best line */
  980.       for (j = ply + 1; nxtline[j] > 0; j++)
  981.         bstline[j] = nxtline[j];
  982.       bstline[j] = 0;
  983.       bstline[ply] = (node->f << 8) | node->t;
  984.       /* if at the top */
  985.       if (ply == 1)
  986.         {
  987.           /*
  988.            * if its better than the root score make it
  989.            * the root
  990.            */
  991.           if ((best > root->score) || ((best == root->score) && (bestwidth > root->width)))
  992.         {
  993.           tmp = Tree[pnt];
  994.           for (j = pnt - 1; j >= 0; j--)
  995.             Tree[j + 1] = Tree[j];
  996.           Tree[0] = tmp;
  997.           pbst = 0;
  998.         }
  999. #ifndef BAREBONES
  1000. #ifdef QUIETBACKGROUND
  1001.           if (!background)
  1002. #endif /* QUIETBACKGROUND */
  1003.         if (Sdepth > 2)
  1004.           if (best > beta)
  1005.             {
  1006.       /* update best line to globle varible *Bstline */
  1007.                         Best = best;
  1008.                         Bch = '+';
  1009.                  for (j = 0; bstline[j] > 0; j++)
  1010.                            Bstline[j] = bstline[j];
  1011.                                Bstline[j]=0;
  1012. //              ShowResults (best, bstline, '+');
  1013.             }
  1014.           else if (best < alpha)
  1015.             {
  1016.       /* update best line to globle varible *Bstline */
  1017.                         Best = best;
  1018.                         Bch = '-';
  1019.                  for (j = 0; bstline[j] > 0; j++)
  1020.                            Bstline[j] = bstline[j];
  1021.                                Bstline[j]=0;
  1022. //              ShowResults (best, bstline, '-');
  1023.             }
  1024.           else {
  1025.       /* update best line to globle varible *Bstline */
  1026.                         Best = best;
  1027.                         Bch = '&';
  1028.                  for (j = 0; bstline[j] > 0; j++)
  1029.                            Bstline[j] = bstline[j];
  1030.                                Bstline[j]=0;
  1031. //            ShowResults (best, bstline, '&');
  1032.                         }
  1033. #endif
  1034.           if (!background && Sdepth > 2){
  1035.              if( best < alpha ) { TCcount = 0;ExtraTime += 9*TCleft;}
  1036.                  }
  1037.         }
  1038.     }
  1039.       if (flag.timeout)
  1040.     {
  1041.       return (Tscore[ply - 1]);
  1042.     }
  1043.     }
  1044.  
  1045.   /******************************************************************************************/
  1046.   node = &Tree[pbst];
  1047.   mv = (node->f << 8) | node->t;
  1048. #ifdef NULLMOVE
  1049.   PVari = PVarisave;
  1050. #endif
  1051.  
  1052.   /*
  1053.    * we have a move so put it in local table - if it's already there
  1054.    * done else if not there or needs to be updated also put it in
  1055.    * hashfile
  1056.    */
  1057. #if ttblsz
  1058.   if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
  1059.     {
  1060.       if (PutInTTable (side, best, depth, ply, alpha, beta, mv)
  1061. #ifdef HASHFILE
  1062.       && hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit))
  1063.     {
  1064.       PutInFTable (side, best, depth, ply, alpha, beta, node->f, node->t);
  1065.     }
  1066. #else
  1067.     );
  1068. #endif /* HASHFILE */
  1069.     }
  1070. #endif /* ttblsz */
  1071.   if (depth > 0)
  1072.     {
  1073. #ifdef HISTORY
  1074.       j = (node->f << 8) | node->t;
  1075.       if (side == black)
  1076.     j |= 0x4000;
  1077.       if (history[j] < HISTORYLIM)
  1078.     history[j] += (unsigned short) 1 << depth;
  1079. #endif
  1080.       if (node->t != (short) (GameList[GameCnt].gmove & 0xFF))
  1081.     if (best <= beta)
  1082.       killr3[ply] = mv;
  1083.     else if (mv != killr1[ply])
  1084.       {
  1085.         killr2[ply] = killr1[ply];
  1086.         killr1[ply] = mv;
  1087.       }
  1088.       killr0[ply] = ((best > 9000) ? mv : 0);
  1089.     }
  1090.   return (best);
  1091. }
  1092.  
  1093.  
  1094.  
  1095.  
  1096. int
  1097. castle (short int side, short int kf, short int kt, short int iop)
  1098.  
  1099. /* Make or Unmake a castling move. */
  1100.  
  1101. {
  1102.   register short rf, rt, t0, xside;
  1103.  
  1104.   xside = side ^ 1;
  1105.   if (kt > kf)
  1106.     {
  1107.       rf = kf + 3;
  1108.       rt = kt - 1;
  1109.     }
  1110.   else
  1111.     {
  1112.       rf = kf - 4;
  1113.       rt = kt + 1;
  1114.     }
  1115.   if (iop == 0)
  1116.     {
  1117.       if (kf != kingP[side] ||
  1118.       board[kf] != king ||
  1119.       board[rf] != rook ||
  1120.       color[kf] != side ||
  1121.       color[rf] != side ||
  1122.       Mvboard[kf] != 0 ||
  1123.       Mvboard[rf] != 0 ||
  1124.       color[kt] != neutral ||
  1125.       color[rt] != neutral ||
  1126.       color[kt - 1] != neutral ||
  1127.       SqAtakd (kf, xside) ||
  1128.       SqAtakd (kt, xside) ||
  1129.       SqAtakd (rt, xside))
  1130.     return (false);
  1131.     }
  1132.   else
  1133.     {
  1134.       if (iop == 1)
  1135.     {
  1136.       castld[side] = true;
  1137.       Mvboard[kf]++;
  1138.       Mvboard[rf]++;
  1139.     }
  1140.       else
  1141.     {
  1142.       castld[side] = false;
  1143.       Mvboard[kf]--;
  1144.       Mvboard[rf]--;
  1145.       t0 = kt;
  1146.       kt = kf;
  1147.       kf = t0;
  1148.       t0 = rt;
  1149.       rt = rf;
  1150.       rf = t0;
  1151.     }
  1152.       board[kt] = king;
  1153.       color[rt] = color[kt] = side;
  1154.       Pindex[kt] = 0;
  1155.       board[kf] = no_piece;
  1156.       color[rf] = color[kf] = neutral;
  1157.       board[rt] = rook;
  1158.       Pindex[rt] = Pindex[rf];
  1159.       board[rf] = no_piece;
  1160.       PieceList[side][Pindex[kt]] = kt;
  1161.       PieceList[side][Pindex[rt]] = rt;
  1162.       UpdateHashbd (side, king, kf, kt);
  1163.       UpdateHashbd (side, rook, rf, rt);
  1164.     }
  1165.   return (true);
  1166. }
  1167.  
  1168.  
  1169. void
  1170. EnPassant (short int xside, short int f, short int t, short int iop)
  1171.  
  1172. /*
  1173.  * Make or unmake an en passant move.
  1174.  */
  1175.  
  1176. {
  1177.   register short l;
  1178.  
  1179.   l = t + ((t > f) ? -8 : 8);
  1180.   if (iop == 1)
  1181.     {
  1182.       board[l] = no_piece;
  1183.       color[l] = neutral;
  1184.     }
  1185.   else
  1186.     {
  1187.       board[l] = pawn;
  1188.       color[l] = xside;
  1189.     }
  1190.   InitializeStats ();
  1191. }
  1192.  
  1193.  
  1194. void
  1195. UpdatePieceList (short int side, short int sq, short int iop)
  1196.  
  1197. /*
  1198.  * Update the PieceList and Pindex arrays when a piece is captured or when a
  1199.  * capture is unmade.
  1200.  */
  1201.  
  1202. {
  1203.   register short i;
  1204.  
  1205.   if (iop == 1)
  1206.     {
  1207.       PieceCnt[side]--;
  1208.       for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1209.     {
  1210.       PieceList[side][i] = PieceList[side][i + 1];
  1211.       Pindex[PieceList[side][i]] = i;
  1212.     }
  1213.     }
  1214.   else
  1215.     {
  1216.       PieceCnt[side]++;
  1217.       PieceList[side][PieceCnt[side]] = sq;
  1218.       Pindex[sq] = PieceCnt[side];
  1219.     }
  1220. }
  1221.  
  1222. void
  1223. MakeMove (short int side,
  1224.       struct leaf *node,
  1225.       short int *tempb,    /* color of to square */
  1226.       short int *tempc,    /* piece at to square */
  1227.       short int *tempsf,    /* static value of piece on from */
  1228.       short int *tempst,    /* static value of piece on to */
  1229.       short int *INCscore)    /* score increment for pawn structure change */
  1230.  
  1231. /*
  1232.  * Update Arrays board[], color[], and Pindex[] to reflect the new board
  1233.  * position obtained after making the move pointed to by node. Also update
  1234.  * miscellaneous stuff that changes when a move is made.
  1235.  */
  1236.  
  1237. {
  1238.   register short f, t, xside, ct, cf;
  1239.   register struct GameRec *g;
  1240.  
  1241.   xside = side ^ 1;
  1242.   g = &GameList[++GameCnt];
  1243.   g->hashkey = hashkey;
  1244.   g->hashbd = hashbd;
  1245.   g->epssq = epsquare;
  1246.   f = node->f;
  1247.   t = node->t;
  1248.   epsquare = -1;
  1249.   /* FROMsquare = f;*/
  1250.   TOsquare = t;
  1251.   *INCscore = 0;
  1252.   g->Game50 = Game50;
  1253.   g->gmove = (f << 8) | t;
  1254.   g->flags = node->flags;
  1255.   if (node->flags & cstlmask)
  1256.     {
  1257.       g->piece = no_piece;
  1258.       g->color = side;
  1259.       (void) castle (side, f, t, 1);
  1260.       Game50 = GameCnt;
  1261.     }
  1262.   else
  1263.     {
  1264.       if (!(node->flags & capture) && (board[f] != pawn))
  1265.     {
  1266.       rpthash[side][hashkey & 0xFF]++;
  1267.       ISZERO++;
  1268.     }
  1269.       else
  1270.     Game50 = GameCnt;
  1271.       *tempsf = svalue[f];
  1272.       *tempst = svalue[t];
  1273.       g->piece = *tempb = board[t];
  1274.       g->color = *tempc = color[t];
  1275.       if (*tempc != neutral)
  1276.     {
  1277.       UpdatePieceList (*tempc, t, 1);
  1278.       /* if capture decrement pawn count */
  1279.       if (*tempb == pawn)
  1280.         {
  1281.           --PawnCnt[*tempc][column (t)];
  1282.         }
  1283.       if (board[f] == pawn)
  1284.         {
  1285.           cf = column (f);
  1286.           ct = column (t);
  1287.           /* move count from from to to */
  1288.           --PawnCnt[side][cf];
  1289.           ++PawnCnt[side][ct];
  1290.  
  1291.           /*
  1292.            * calculate increment for pawn structure
  1293.            * changes
  1294.            */
  1295.           /* doubled or more - */
  1296.           if (PawnCnt[side][ct] > (1 + PawnCnt[side][cf]))
  1297.         *INCscore -= 15;
  1298.           /* went to empty column + */
  1299.           else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1300.         *INCscore += 15;
  1301.  
  1302.           /*
  1303.            * went to outside col or empty col on one
  1304.            * side ????????
  1305.            */
  1306.           else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1307.         *INCscore -= 15;
  1308.         }
  1309.       mtl[xside] -= value[*tempb];
  1310.       if (*tempb == pawn)
  1311.         pmtl[xside] -= valueP;
  1312.       UpdateHashbd (xside, *tempb, -1, t);
  1313.       *INCscore += *tempst;
  1314.       Mvboard[t]++;
  1315.     }
  1316.       color[t] = color[f];
  1317.       board[t] = board[f];
  1318.       svalue[t] = svalue[f];
  1319.       Pindex[t] = Pindex[f];
  1320.       PieceList[side][Pindex[t]] = t;
  1321.       color[f] = neutral;
  1322.       board[f] = no_piece;
  1323.       if (board[t] == pawn)
  1324.     if (t - f == 16)
  1325.       epsquare = f + 8;
  1326.     else if (f - t == 16)
  1327.       epsquare = f - 8;
  1328.       if (node->flags & promote)
  1329.     {
  1330.       board[t] = node->flags & pmask;
  1331.       if (board[t] == queen)
  1332.         HasQueen[side]++;
  1333.       else if (board[t] == rook)
  1334.         HasRook[side]++;
  1335.       else if (board[t] == bishop)
  1336.         HasBishop[side]++;
  1337.       else if (board[t] == knight)
  1338.         HasKnight[side]++;
  1339.       --PawnCnt[side][column (t)];
  1340.       mtl[side] += value[board[t]] - valueP;
  1341.       pmtl[side] -= valueP;
  1342.       UpdateHashbd (side, pawn, f, -1);
  1343.       UpdateHashbd (side, board[t], f, -1);
  1344.       *INCscore -= *tempsf;
  1345.     }
  1346.       if (node->flags & epmask)
  1347.     EnPassant (xside, f, t, 1);
  1348.       else
  1349.     UpdateHashbd (side, board[t], f, t);
  1350.       Mvboard[f]++;
  1351.     }
  1352. }
  1353.  
  1354. void
  1355. UnmakeMove (short int side,
  1356.         struct leaf *node,
  1357.         short int *tempb,
  1358.         short int *tempc,
  1359.         short int *tempsf,
  1360.         short int *tempst)
  1361.  
  1362. /*
  1363.  * Take back a move.
  1364.  */
  1365.  
  1366. {
  1367.   register short f, t, xside;
  1368.  
  1369.   xside = side ^ 1;
  1370.   f = node->f;
  1371.   t = node->t;
  1372.   Game50 = GameList[GameCnt].Game50;
  1373.   if (node->flags & cstlmask)
  1374.     (void) castle (side, f, t, 2);
  1375.   else
  1376.     {
  1377.       color[f] = color[t];
  1378.       board[f] = board[t];
  1379.       svalue[f] = *tempsf;
  1380.       Pindex[f] = Pindex[t];
  1381.       PieceList[side][Pindex[f]] = f;
  1382.       color[t] = *tempc;
  1383.       board[t] = *tempb;
  1384.       svalue[t] = *tempst;
  1385.       if (node->flags & promote)
  1386.     {
  1387.       board[f] = pawn;
  1388.       ++PawnCnt[side][column (t)];
  1389.       mtl[side] += valueP - value[node->flags & pmask];
  1390.       pmtl[side] += valueP;
  1391.       UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  1392.       UpdateHashbd (side, pawn, -1, t);
  1393.     }
  1394.       if (*tempc != neutral)
  1395.     {
  1396.       UpdatePieceList (*tempc, t, 2);
  1397.       if (*tempb == pawn)
  1398.         {
  1399.           ++PawnCnt[*tempc][column (t)];
  1400.         }
  1401.       if (board[f] == pawn)
  1402.         {
  1403.           --PawnCnt[side][column (t)];
  1404.           ++PawnCnt[side][column (f)];
  1405.         }
  1406.       mtl[xside] += value[*tempb];
  1407.       if (*tempb == pawn)
  1408.         pmtl[xside] += valueP;
  1409.       UpdateHashbd (xside, *tempb, -1, t);
  1410.       Mvboard[t]--;
  1411.     }
  1412.       if (node->flags & epmask)
  1413.     {
  1414.       EnPassant (xside, f, t, 2);
  1415.     }
  1416.       else
  1417.     UpdateHashbd (side, board[f], f, t);
  1418.       Mvboard[f]--;
  1419.       if (!(node->flags & capture) && (board[f] != pawn))
  1420.     {
  1421.       rpthash[side][hashkey & 0xFF]--;
  1422.       ISZERO--;
  1423.     }
  1424.     }
  1425.   epsquare = GameList[GameCnt--].epssq;
  1426. }
  1427.  
  1428.  
  1429. void
  1430. InitializeStats (void)
  1431.  
  1432. /*
  1433.  * Scan thru the board seeing what's on each square. If a piece is found,
  1434.  * update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  1435.  * determine the material for each side and set the hashkey and hashbd
  1436.  * variables to represent the current board position. Array
  1437.  * PieceList[side][indx] contains the location of all the pieces of either
  1438.  * side. Array Pindex[sq] contains the indx into PieceList for a given
  1439.  * square.
  1440.  */
  1441.  
  1442. {
  1443.   register short i, sq;
  1444.  
  1445.   epsquare = -1;
  1446.   for (i = 0; i < 8; i++)
  1447.     {
  1448.       PawnCnt[white][i] = PawnCnt[black][i] = 0;
  1449.     }
  1450.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  1451.   PieceCnt[white] = PieceCnt[black] = 0;
  1452.   hashbd = hashkey = 0;
  1453.   for (sq = 0; sq < 64; sq++)
  1454.     if (color[sq] != neutral)
  1455.       {
  1456.     mtl[color[sq]] += value[board[sq]];
  1457.     if (board[sq] == pawn)
  1458.       {
  1459.         pmtl[color[sq]] += valueP;
  1460.         ++PawnCnt[color[sq]][column (sq)];
  1461.       }
  1462.     Pindex[sq] = ((board[sq] == king) ? 0 : ++PieceCnt[color[sq]]);
  1463.  
  1464.     PieceList[color[sq]][Pindex[sq]] = sq;
  1465.     hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  1466.     hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  1467.       }
  1468. }
  1469.